import {
  AmbientLight,
  AxesHelper,
  BoxGeometry,
  CubeTextureLoader,
  CylinderGeometry,
  DirectionalLight,
  DoubleSide,
  Group,
  Mesh,
  MeshBasicMaterial,
  MeshStandardMaterial,
  PerspectiveCamera,
  RepeatWrapping,
  Scene,
  Shape,
  ShapeGeometry,
  SRGBColorSpace,
  TextureLoader,
  Vector2,
  WebGLRenderer,
} from "three";
import { OrbitControls } from "three/examples/jsm/Addons.js";
import SolidAbutment from "./SolidAbutment";
import SolidUAbutment from "./SolidUAbutment";

console.log("桥台");

function cumsum(points) {
  const a = new Vector2();
  const b = new Vector2();
  const res = [];
  for (const pt of points) {
    b.set(pt[0], pt[1]);
    res.push(a.add(b).clone());
  }
  return res;
}

const textureLoader = new TextureLoader();

function load_standard_material_url({
  url,
  normalUrl = null,
  color = 0xf6f6f6,
  opacity = 0.9,
  renderOrder = 1,
  repeatFactor = 0.05,
}) {
  const texture = textureLoader.load(url);
  texture.colorSpace = SRGBColorSpace;
  texture.wrapS = RepeatWrapping;
  texture.wrapT = RepeatWrapping;
  texture.repeat.set(repeatFactor, repeatFactor);
  const textureNormal = normalUrl && textureLoader.load(normalUrl);
  if (textureNormal) {
    textureNormal.wrapS = RepeatWrapping;
    textureNormal.wrapT = RepeatWrapping;
  }
  const material = new MeshStandardMaterial({
    color,
    map: texture,
    side: DoubleSide,
    normalMap: textureNormal,
    normalScale: new Vector2(5, 5),
    transparent: true,
    roughness: 0.9,
    metalness: 0.05,
    opacity,
  });

  material.userData.renderOrder = renderOrder;
  return material;
}

function load_standard_material({
  path = "../assets",
  name,
  postfix,
  color = 0xf6f6f6,
  renderOrder = 1,
  repeatFactor = 0.05,
}) {
  return load_standard_material_url({
    url: `${path}/${name}.${postfix}`,
    normalUrl: `${path}/${name}_normal.${postfix}`,
    color,
    renderOrder,
    repeatFactor,
  });
}

const drain_pipe_top_material = load_standard_material({
  name: "drain_pipe",
  postfix: "jpg",
  color: 0xffffff,
  opacity: 1,
  renderOrder: 1,
  repeatFactor: 1,
});
const drain_pipe_side_material = load_standard_material({
  name: "px130",
  postfix: "png",
  color: 0xffffff,
  opacity: 1,
  renderOrder: 1,
  repeatFactor: 1,
});

const drain_pipe_material = [
  drain_pipe_side_material,
  drain_pipe_top_material,
  drain_pipe_top_material,
];

class Y3Engine {
  constructor() {
    this.initScene();
    this.initHelper();
    this.initCamera();
    this.initLight();
    this.initRenderer();
    this.initControls();
    this.initModel();
    this.animate();
  }

  initHelper() {
    this.helpers = new Group();
    const axesHelper = new AxesHelper(5);
    this.helpers.add(axesHelper);
    this.scene.add(this.helpers);
    // const axesHelper2 = new AxesHelper(5);
    // axesHelper2.position.set(5, 5, 5);
    // this.helpers.add(axesHelper2);
  }

  createCylinder() {
    const geometry = new CylinderGeometry(5, 5, 15);

    const mesh = new Mesh(geometry, drain_pipe_material);

    this.model.add(mesh);
  }

  initModel() {
    const model = new Group();
    this.model = model;
    this.scene.add(model);
    this.createCylinder();
    const material = new MeshStandardMaterial({
      color: 0xa0a0a0,
      metalness: 0.5,
      roughness: 1,
    });
    if (0) {
      const box = new BoxGeometry(1, 1, 1);
      const mesh = new Mesh(box, material);
      model.add(mesh);
    }

    if (0) {
      const abutment = new SolidUAbutment({
        deckWidth: 20,
        side_wall_k: 0,
        body_slope_m: 0,
      });
      const mesh = new Mesh(abutment.geometry.clone(), material);
      mesh.position.set(0, -10, 0);
      mesh.name = "桥台";
      model.add(mesh);

      const mesh2 = new Mesh(abutment.reverseGeometry, material);
      mesh2.position.set(0, 10, 0);
      mesh2.name = "终止桥台";
      model.add(mesh2);
      console.log(mesh2);
    }
    if (0) {
      const points = cumsum([
        [0, 0],
        [-2.3, 0],
        [0, -5],
        [0.75, 0],
      ]);
      console.log(points);
      const shape = new Shape(points);

      const geometry = new ShapeGeometry(shape);
      const material = new MeshBasicMaterial({
        color: 0xff0000,
        side: DoubleSide,
      });
      // geometry.translate(1, 0, 0);
      const mesh = new Mesh(geometry, material);
      model.add(mesh);
    }
  }

  initScene() {
    this.scene = new Scene();
  }

  initCamera() {
    this.camera = new PerspectiveCamera(
      75,
      window.innerWidth / window.innerHeight,
      0.1,
      1000
    );
    this.camera.up.set(0, 0, 1);
    this.camera.position.set(25, 0, 0);
  }
  initLight() {
    this.lights = new Group();
    this.scene.add(this.lights);

    const light = new AmbientLight(0xffffff, 0.3);
    this.lights.add(light);

    const light2 = new DirectionalLight(0xffffff, 0.8);
    light2.position.set(1, 1, 0);
    this.lights.add(light2);

    const light3 = new DirectionalLight(0xffffff, 0.5);
    light3.position.set(-1, 1, 0);
    this.lights.add(light3);

    const light4 = new DirectionalLight(0xffffff, 0.2);
    light4.position.set(0, -1, 0);
    this.lights.add(light4);

    const url = "px180.png";
    const cubeTexture = new CubeTextureLoader()
      .setPath("../assets/")
      .load([url, url, url, url, url, url]);
    this.scene.environment = cubeTexture;
    this.scene.environmentIntensity = 0.5;
  }

  initRenderer() {
    this.renderer = new WebGLRenderer({ antialias: true });
    this.renderer.setPixelRatio(window.devicePixelRatio);
    this.renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(this.renderer.domElement);
  }

  initControls() {
    this.controls = new OrbitControls(this.camera, this.renderer.domElement);
  }

  animate = () => {
    requestAnimationFrame(this.animate);
    this.renderer.render(this.scene, this.camera);
  };
}

window.y3Engine = new Y3Engine();
